/**
 * 
 */
package linkedlist.passed2;

/**
 * @author michael
Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

begin to intersect at node c1.

Notes:

    If the two linked lists have no intersection at all, return null.
    The linked lists must retain their original structure after the function returns.
    You may assume there are no cycles anywhere in the entire linked structure.
    Your code should preferably run in O(n) time and use only O(1) memory.

 */
public class IntersectionOfTwoLinkedLists {

	
	 //Definition for singly-linked list.
	 public class ListNode {
	      int val;
	      ListNode next;
	      ListNode(int x) {
	          val = x;
	          next = null;
	      }
	 }
	 
	// time O(n) space O(1)
    public ListNode getIntersectionNode1(ListNode headA, ListNode headB) {
        int sizeA = getSize(headA);
        int sizeB = getSize(headB);
        
        while (sizeA > sizeB) {
        	headA = headA.next;
        	sizeA--;
        }
        while (sizeB > sizeA) {
        	headB = headB.next;
        	sizeB--;
        }
        
        while (headA != headB) {
        	headA = headA.next;
        	headB = headB.next;
        }
        
        return headA;
    }
    
    private int getSize(ListNode head) {
    	int size = 0;
    	while (head != null) {
    		head = head.next;
    		size++;
    	}
    	
    	return size;
    }
    
	
	// time O(n) space O(1)
    public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
    	ListNode nodeA = headA;
        ListNode nodeB = headB;
        if (nodeA == null || nodeB == null) return null;
        while (nodeA != null && nodeB != null && nodeA != nodeB) {
        	nodeA = nodeA.next;
        	nodeB = nodeB.next;
        	if (nodeA == nodeB)
        		break;
        	if (nodeA == null)
        		nodeA = headB;
        	else if (nodeB == null)
        		nodeB = headA;
        }
        
        return nodeA;
    }
    
	// time O(n) space O(n), by using stack
    public ListNode getIntersectionNode3(ListNode headA, ListNode headB) {
        return null;
    }    
	
	/**
	 * 
	 */
	public IntersectionOfTwoLinkedLists() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
